/**
* 版权声明：厦门睿商网络科技有限公司 版权所有 违者必究
* 日    期：2020-04-27
*/
package com.rzico.account.service;

import com.alibaba.fastjson.JSON;
import com.rzico.account.model.CompanyCardDetailVo;
import com.rzico.account.model.CompanyCardVo;
import com.rzico.account.model.EmployeeCardVo;
import com.rzico.basics.entity.*;
import com.rzico.account.entity.Payment;
import com.rzico.account.entity.Refunds;
import com.rzico.basics.mapper.CardMapper;
import com.rzico.account.mapper.PaymentMapper;
import com.rzico.account.mapper.RefundsMapper;
import com.rzico.account.model.Attach;
import com.rzico.base.BaseMapper;
import com.rzico.base.impl.BaseServiceImpl;
import com.rzico.account.entity.CardBill;
import com.rzico.account.mapper.CardBillMapper;
import com.rzico.basics.mapper.CardTagMapper;
import com.rzico.account.model.CardExtVo;
import com.rzico.basics.service.CompanyService;
import com.rzico.basics.service.EnterpriseService;
import com.rzico.basics.service.MemberService;
import com.rzico.basics.service.MsgService;
import com.rzico.core.entity.SysPlugin;
import com.rzico.core.entity.SysTemplate;
import com.rzico.core.entity.SysUser;
import com.rzico.core.plugin.MsgPlugin;
import com.rzico.core.service.SysPluginService;
import com.rzico.core.service.SysTemplateService;
import com.rzico.core.service.SysUserService;
import com.rzico.exception.CustomException;
import com.rzico.util.DateUtils;
import com.rzico.util.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Lazy;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.math.BigDecimal;
import java.text.DateFormat;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.*;

/**
 * <pre>
 * 会员卡账单业务类
 * </pre>
 *
 * @author Rzico Boot
 * @version 1.0
 */
@Service
public class CardBillService extends BaseServiceImpl<CardBill, String> {

    @Autowired
    private CardBillMapper cardBillMapper;

    @Autowired
    private CardMapper cardMapper;
    @Autowired
    private RefundsMapper refundsMapper;
    @Autowired
    private PaymentMapper paymentMapper;
    @Autowired
    private CardTagMapper cardTagMapper;

    @Autowired @Lazy
    private MsgService msgService;

    @Autowired
    private MemberService memberService;

    @Autowired
    private CompanyService companyService;

    @Autowired
    private EnterpriseService enterpriseService;

    @Autowired
    private SysUserService sysUserService;

    @Autowired
    private SysPluginService sysPluginService;

    @Autowired
    private SysTemplateService sysTemplateService;

    @Override
    public BaseMapper<CardBill, String> getMapper() {
        return cardBillMapper;
    }

    //付款
    @Transactional(rollbackFor = Exception.class)
    public void payment(Payment payment) {

        if (!payment.getStatus().equals(Payment.STATUS_WAITING)) {
            throw new CustomException("不是待付款状态");
        }


        //更新重新读取余额
        Attach attach = payment.decodeAttach();
        Card card = cardMapper.selectByPrimaryKey(attach.getCardId());

        String cardName = "会员卡";
        if (card.getCardType().equals(1)) {
            cardName = "福利卡";
            if (card.getMemo() != null) {
                cardName = card.getMemo();
            }
        }

        payment.setStatus(Payment.STATUS_SUCCESS);
        payment.setPaymentDate(new Date());
        payment.setPaymentPluginId("cardPayPlugin");
        payment.setPaymentPluginName(cardName);
        paymentMapper.updateByPrimaryKeySelective(payment);

        if (card.getBalance().compareTo(payment.getAmount())<0) {
            throw new CustomException("卡余额不足");
        }
        Map<String,Object> updateParams = new HashMap<>();
        updateParams.put("id",card.getId());
        updateParams.put("value",payment.getAmount());
        cardMapper.decBalance(updateParams);

        card = cardMapper.selectByPrimaryKey(attach.getCardId());
        if (card.getBalance().compareTo(BigDecimal.ZERO)<0) {
            throw new CustomException("卡余额不足");
        }

        CardBill cardBill = new CardBill();
        cardBill.setCardId(card.getId());
        cardBill.setBalance(card.getBalance());
        cardBill.setDebit(payment.getAmount());
        cardBill.setCredit(BigDecimal.ZERO);
        cardBill.setCreateDate(new Date());
        cardBill.setDeleted(false);
        cardBill.setEnterpriseId(payment.getEnterpriseId());
        cardBill.setMemberId(payment.getMemberId());
        cardBill.setMemo(payment.getMemo());
        cardBill.setPaymentId(payment.getId());
        cardBill.setType(1);
        cardBill.setShopId(payment.getShopId());
        cardBill.setDeleted(false);
        cardBillMapper.insertUseGeneratedKeys(cardBill);

        Map<String,Object> content = new HashMap<>();
        if (card.getCardType().equals(1)) {
            content.put("title", "付款成功-"+cardName+"(" + card.getCode().substring(card.getCode().length() - 4) + ")");
        } else {
            content.put("title", "付款成功-会员卡");
        }
        content.put("memo",payment.getMemo());
        content.put("amount",payment.getAmount());
        content.put("balance",cardBill.getBalance());
        content.put("type",2);
        if (card.getEndDate()!=null) {
            content.put("expireDate",card.getEndDate());
        }
        content.put("id",card.getId());
        Member member = memberService.findById(card.getMemberId());
        msgService.sendNotity(member,"msg-account",content.get("title").toString(), JSON.toJSONString(content),null);


    }
    //退款
    @Transactional(rollbackFor = Exception.class)
    public void refunds(Refunds refunds) {
        if (!refunds.getStatus().equals(Refunds.STATUS_WAITING)) {
            throw new CustomException("不是待退款状态");
        }

        Attach attach = refunds.decodeAttach();
        Card card = cardMapper.selectByPrimaryKey(attach.getCardId());

        String cardName = "会员卡";
        if (card.getCardType().equals(1)) {
            cardName = "福利卡";
            if (card.getMemo() != null) {
                cardName = card.getMemo();
            }
        }

        refunds.setStatus(Refunds.STATUS_REFUNDED);
        refunds.setRefundsDate(new Date());
        refunds.setPaymentPluginId("cardPayPlugin");
        refunds.setPaymentPluginName(cardName);
        refundsMapper.updateByPrimaryKeySelective(refunds);

        Map<String,Object> updateParams = new HashMap<>();
        updateParams.put("id",card.getId());
        updateParams.put("value",refunds.getAmount());
        cardMapper.addBalance(updateParams);
        //更新重新读取余额
        card = cardMapper.selectByPrimaryKey(attach.getCardId());

        CardBill cardBill = new CardBill();
        cardBill.setCardId(card.getId());
        cardBill.setBalance(card.getBalance());
        cardBill.setDebit(BigDecimal.ZERO);
        cardBill.setCredit(refunds.getAmount());
        cardBill.setCreateDate(new Date());
        cardBill.setDeleted(false);
        cardBill.setEnterpriseId(refunds.getEnterpriseId());
        cardBill.setMemberId(refunds.getMemberId());
        cardBill.setMemo(refunds.getMemo());
        cardBill.setRefundsId(refunds.getId());
        cardBill.setType(2);
        cardBill.setShopId(refunds.getShopId());
        cardBill.setDeleted(false);
        cardBillMapper.insertUseGeneratedKeys(cardBill);


        Map<String,Object> content = new HashMap<>();
        if (card.getCardType().equals(1)) {
            content.put("title", "退款成功-"+cardName+"(" + card.getCode().substring(card.getCode().length() - 4) + ")");
        } else {
            content.put("title", "退款成功-会员卡");
        }
        content.put("memo",refunds.getMemo());
        content.put("amount",refunds.getAmount());
        content.put("balance",cardBill.getBalance());
        content.put("type",2);
        if (card.getEndDate()!=null) {
            content.put("expireDate",card.getEndDate());
        }
        content.put("id",card.getId());
        Member member = memberService.findById(card.getMemberId());
        msgService.sendNotity(member,"msg-account",content.get("title").toString(), JSON.toJSONString(content),null);

    }


    /**
     * 企业员工充值接口
     * 验证导入得名单是否均为本企业员工，若员工信息错误则提示返回，不进行充值
     *
     * @param list
     * @param companyId
     * @param cardType
     * @return
     */
    public Map<String, Object> checkUploadInfo(List<CardExtVo> list, Long enterpriseId, Long companyId, Integer cardType,
                                               String memo, String startDate, String endDate){
        Map<String,Object> result = new HashMap<>();
        result.put("returnCode","success");
        /*
         * 先用手机号查询member表,判断当前员工是否存在，
         * 再根据memberid与companyid查询companyemployee表判断员工是否在当前企业就职
         */
        for (CardExtVo cardExtVo : list) {
            //Member member = memberService.findByMobile(enterpriseId,cardExtVo.getMobile());
            //不检查员工
            /*if (null != member){
                Map<String, Object> params = new HashMap<String, Object>();
                params.put("memberId", member.getId());
                params.put("status", 1);
                params.put("enterpriseId", enterpriseId);
                List<CompanyEmployee> employeeList = companyEmployeeService.selectList(params);
                if (0 < employeeList.size()){
                    for (CompanyEmployee companyEmployee:employeeList) {
                        if (!companyEmployee.getCompanyId().equals(companyId) ) {
                            Company company = companyService.selectByPrimaryKey(companyId);
                            cardExtVo.setResult(company.getName() + "已存在该手机号");
                            result.put("returnCode","error");
                            break;
                        }
                    }
                } else {
                    cardExtVo.setResult("该手机号还不是该企业员工");
                    result.put("returnCode","error");
                }
            } else {
                cardExtVo.setResult("该手机号尚未注册");
                result.put("returnCode","error");
            }*/
            if (StringUtils.isEmpty(cardExtVo.getCode()) || cardType==0) {
                if (StringUtils.isEmpty(cardExtVo.getMobile())) {
                    cardExtVo.setResult("手机号不能为空");
                    result.put("returnCode", "error");
                }
                if (StringUtils.isEmpty(cardExtVo.getName())) {
                    cardExtVo.setResult("姓名不能为空");
                    result.put("returnCode", "error");
                }
            }
            if (StringUtils.isEmpty(memo)) {
                cardExtVo.setResult("未填写福利名称");
                result.put("returnCode","error");
            }
            if (1 == cardType && (StringUtils.isEmpty(startDate) || StringUtils.isEmpty(endDate))) {
                cardExtVo.setResult("未设置有效期");
                result.put("returnCode","error");
            }
            if (0 >= cardExtVo.getAmount().compareTo(BigDecimal.ZERO)) {
                cardExtVo.setResult("充值金额错误");
                result.put("returnCode","error");
            }
        }

        result.put("vo",list);
        return result;
    }

    /**
     * 验证导入得金额类型，若为储存卡，则每一个用户只能有一条记录（先更新金额），若为福利卡则直接建卡充值
     * 充值完后需生成流水记录
     */
    @Transactional(rollbackFor = Exception.class)
    public List<CardExtVo> upload(List<CardExtVo> dataList, Long enterpriseId, Long companyId, Integer cardType, String code,
                                  String memo, String startDate, String endDate, Long[] tagIds, String mchId){
        List<Card> cList = new ArrayList<Card>();
        List<Map<String, Object>> msgMapList = new ArrayList<Map<String, Object>>();
        /*
         * 判断充值的金额类型，分存储卡和福利金
         * 若为存储卡，则先查找卡记录，若未存在，则需先建卡充值并生成流水记录，若已存在则更新金额，再生成流水记录
         * 若为福利卡，则直接建卡，生成流水记录
         */

        Date createDate = new Date();
        String companyName = "";
        Company company = companyService.findById(companyId);
        if (null != company) {
            companyName = company.getName();
        }
        Enterprise enterprise = enterpriseService.selectByPrimaryKey(enterpriseId);
        int codeNum = 0;
        for (CardExtVo cardExtVo : dataList) {
            Member member = null;
            if (StringUtils.isNotEmpty(cardExtVo.getMobile())) {
                member = memberService.findByMobile(enterpriseId, cardExtVo.getMobile());
                if (member == null) {
                    //如果没自动添加注册会员
                    member = new Member();
                    member.setCreateDate(createDate);
                    member.setUsername("mch_" + enterprise.getMchId() + "_" + cardExtVo.getMobile());
                    member.setMchId(enterprise.getMchId());
                    member.setDeleted(false);
                    member.setMobile(cardExtVo.getMobile());
                    member.setPhone(cardExtVo.getMobile());
                    member.setName(cardExtVo.getName());
                    member.setVip(0);
                    member.setEnterpriseId(enterpriseId);
                    member.setFreezePoint(0L);
                    member.setBalance(BigDecimal.ZERO);
                    member.setFreezeBalance(BigDecimal.ZERO);
                    member.setAmount(BigDecimal.ZERO);
                    member.setPoint(0L);
                    member.setAmount(BigDecimal.ZERO);
                    member.setMemberType(0);
                    member.setGender(2);
                    member.setTaxType(0);
                    memberService.insertUseGeneratedKeys(member);
                }
            }
            if (0 == cardType) {
                if (member==null) {
                    cardExtVo.setResult("无效会员");
                    throw new CustomException("无效会员手机号");
                }
                //先通过手机号查找是否已经建卡
                Map<String,Object> params = new HashMap<>();
                params.put("memberId", member.getId());
                params.put("cardType", 0);
                params.put("enterpriseId", enterpriseId);
                List<Card> cardList = cardMapper.selectList(params);
                Card newCard = null;
                if (cardList.size()==0) {
                    codeNum ++;
                    newCard = new Card();
                    newCard.setCreateDate(createDate);
                    newCard.setModifyDate(createDate);
                    newCard.setBalance(BigDecimal.ZERO);
                    newCard.setMemo(memo);
                    if (cardExtVo.getCode()!=null && !"".equals(cardExtVo.getCode().trim())) {
                        newCard.setCode(cardExtVo.getCode());
                    } else {
                        newCard.setCode(code + "-" + codeNum);
                    }
                    newCard.setStatus(1);
                    newCard.setMemberId(member.getId());
                    newCard.setCardType(0);
                    newCard.setEnterpriseId(enterpriseId);
                    cardMapper.insertUseGeneratedKeys(newCard);
                } else {
                    newCard = cardList.get(0);
                }
                Map<String,Object> updateParams = new HashMap<>();
                updateParams.put("id",newCard.getId());
                updateParams.put("value", cardExtVo.getAmount());
                cardMapper.addBalance(updateParams);

                //若已建卡则更新金额添加流水
                CardBill cardBill = new CardBill();
                cardBill.setCardId(newCard.getId());
                cardBill.setBalance(cardExtVo.getAmount());
                cardBill.setDebit(BigDecimal.ZERO);
                cardBill.setCredit(cardExtVo.getAmount());
                cardBill.setCreateDate(new Date());
                cardBill.setModifyDate(new Date());
                cardBill.setDeleted(false);
                cardBill.setEnterpriseId(enterpriseId);
                cardBill.setMemberId(member.getId());
                cardBill.setMemo( "充值-"  + companyName + memo );
                cardBill.setType(0);
                cardBillMapper.insertUseGeneratedKeys(cardBill);

            } else {
                codeNum ++;
                Card newCard = new Card();
                newCard.setCreateDate(createDate);
                newCard.setModifyDate(createDate);
                newCard.setBalance(cardExtVo.getAmount());
                if (cardExtVo.getCode()!=null && !"".equals(cardExtVo.getCode().trim())) {
                    newCard.setCode(cardExtVo.getCode());
                } else {
                    newCard.setCode(code + "-" + codeNum);
                }
                if (member==null) {
                    newCard.setStatus(0);
                    newCard.setMemberId(null);
                } else {
                    newCard.setStatus(1);
                    newCard.setMemberId(member.getId());
                }
                newCard.setCompanyId(companyId);
                newCard.setStartDate(DateUtils.getDate(startDate + " 00:00:00", "yyyy-MM-dd HH:mm:ss"));
                newCard.setEndDate(DateUtils.getDate(endDate + " 23:59:59", "yyyy-MM-dd HH:mm:ss"));
                newCard.setMemo(memo);
                newCard.setCardType(1);
                newCard.setEnterpriseId(enterpriseId);
                cardMapper.insertUseGeneratedKeys(newCard);

                    cList.add(newCard);
                    Map<String, Object> map = new HashMap<String, Object>();
                    map.put("mobile", cardExtVo.getMobile());
                    map.put("amount", cardExtVo.getAmount());
                    msgMapList.add(map);

                    CardBill cardBill = new CardBill();
                    cardBill.setCardId(newCard.getId());
                    cardBill.setBalance(cardExtVo.getAmount());
                    cardBill.setDebit(BigDecimal.ZERO);
                    cardBill.setCredit(cardExtVo.getAmount());
                    cardBill.setCreateDate(new Date());
                    cardBill.setModifyDate(new Date());
                    cardBill.setDeleted(false);
                    cardBill.setEnterpriseId(enterpriseId);
                if (member!=null) {
                    cardBill.setMemberId(member.getId());
                }
                    cardBill.setMemo("充值-" + companyName + memo);
                    cardBill.setType(0);
                    cardBillMapper.insertUseGeneratedKeys(cardBill);


                //添加标签
                if (tagIds!=null) {
                    for (Long tagId : tagIds) {
                        CardTag cardTag = new CardTag();
                        cardTag.setCards(newCard.getId());
                        cardTag.setTags(tagId);
                        cardTagMapper.insert(cardTag);
                    }
                }
            }
        }

        for (Card card : cList) {
            Member member = memberService.findById(card.getMemberId());
            if (StringUtils.isNotEmpty(member.getUserId())) {
                Map<String,Object> content = new HashMap<>();
                content.put("title", "充值成功-"+card.getMemo()+"(" + card.getCode().substring(card.getCode().length() - 4) + ")");
                content.put("memo", memo);
                content.put("amount", card.getBalance());
                content.put("balance", card.getBalance());
                content.put("type",2);
                if (card.getEndDate()!=null) {
                    content.put("expireDate",card.getEndDate());
                }
                content.put("id",card.getId());
                msgService.sendNotity(member,"msg-account",content.get("title").toString(), JSON.toJSONString(content),null);
            }
        }

        try {

            sendUploadMsg(mchId, msgMapList, memo, endDate);
        } catch (Exception e) {

        }

        return dataList;

    }

    /**
     * 充值成功后发送短信通知
     * @param
     */
    public void sendUploadMsg(String mchId, List<Map<String, Object>> msgMapList, String memo, String endDate){
        SysUser sysUser = null;
        //获取消息模块前要先获取用户
        String tplKey = "msg.cardUpload";
        SysPlugin sysPlugin = sysPluginService.getEnabledPlugin(mchId,SysPlugin.MSGPLUGIN);
        if (sysPlugin==null) {
            sysUser = sysUserService.findByUsername("admin");
            mchId = sysUser.getMchId();
            sysPlugin = sysPluginService.getEnabledPlugin(mchId,SysPlugin.MSGPLUGIN);
        }
        if (sysPlugin==null) {
            throw new CustomException("消息插件未安装");
        }
        SysTemplate template = sysTemplateService.findByTplKey(mchId,tplKey);
        if (null == template){
            sysUser = sysUserService.findByUsername("admin");
            mchId = sysUser.getMchId();
            template = sysTemplateService.findByTplKey(mchId,tplKey);
        }

        if (null == template) {
            throw new CustomException("消息模版不存在");
        }
        MsgPlugin msgPlugin = sysPluginService.getMsgPlugin(sysPlugin.getPluginId());
        for (Map map : msgMapList) {
            Map<String, Object> model = new HashMap<>();
            model.put("amount", map.get("amount"));
            model.put("memo", memo);
            model.put("endDate", endDate);
            model.put("time", DateUtils.getTimeStr(new Date(), DateUtils.HYPHEN_DISPLAY_DATE));
            String msg = sysTemplateService.encodeMsg(template, model);
            try {
                msgPlugin.sendMsg(sysPlugin, map.get("mobile").toString(), msg);
            } catch (Exception e) {
                throw new CustomException("发送消息出错");
            }
        }
    }

    /**
     * 获取企业的福利金余额
     * @param params
     * @return
     */
    public BigDecimal getCompanyBalance(Map<String, Object> params){
        BigDecimal balance = cardMapper.getCompanyBalance(params);
        if (null == balance){
            balance = new BigDecimal(0);
        }
        return balance;
    }

    /**
     * 删除福利金卡及卡充值信息，若产生消费记录则不删除
     * @param params
     * @return
     */
    @Transactional(rollbackFor = Exception.class)
    public int deleteCardAndBillById(Map<String, Object> params) {
        List<Card> list = cardMapper.selectList(params);
        int result = 0;
        //待删除卡数量
        int size = list.size();
        //删除的卡的数量
        int count = 0;
        //查询福利金卡消费记录参数
        Map<String, Object> deParams = new HashMap<String, Object>();
        //查询福利金卡充值记录参数
        Map<String, Object> creParams = new HashMap<String, Object>();
        /*
         * 遍历id，查询每张卡是否产生消费记录，若无则将卡删除，并将充值记录删除，若又则不删除
         */
        for (Card card : list) {
            deParams.put("cardId", card.getId());
            deParams.put("type", 1);
            Integer num = cardBillMapper.selectRowCount(deParams);
            if (0 == num) {
                creParams.put("cardId", card.getId());
                creParams.put("type", 0);
                Long cardid = cardBillMapper.selectList(creParams).get(0).getId();
                cardBillMapper.deleteByPrimaryKey(cardid);
                int deleteCard = super.deleteByPrimaryKey(card.getId());
                count += deleteCard;
            }
        }
        if (size == count) {
            result = 0;
        } else if (size > count && count > 0) {
            result = 1;
        } else if (0 == count) {
            result = 2;
        }
        return result;
    }

    /**
     * 获取企业的所发放的福利卡
     * @param params
     * @return
     */
    public List<CompanyCardVo> selectCompanyAllCard(Map<String, Object> params){
        List<CompanyCardVo> list = cardBillMapper.selectCompanyAllCard(params);
        return list;
    }

    /**
     * 获取企业所发放的某张福利卡详细信息（每个员工充值信息）
     * @param params
     * @return
     */
    public List<CompanyCardDetailVo> selectCompanyCardDetail(Map<String, Object> params){
        List<CompanyCardDetailVo> list = cardBillMapper.selectCompanyCardDetail(params);
        return list;
    }

    /**
     * 获取企业员工得福利卡信息
     * @param params
     * @return
     */
    public List<EmployeeCardVo> selectCompanyEmployeeCard(Map<String, Object> params){
        List<EmployeeCardVo> list = cardBillMapper.selectCompanyEmployeeCard(params);
        return list;
    }

    public void scaner(Card card,Member member) {

        card.setStatus(1);
        card.setMemberId(member.getId());
        card.setBalance(null);
        cardMapper.updateByPrimaryKeySelective(card);

        Map<String,Object> params = new HashMap<>();
        params.put("cardId",card.getId());
        List<CardBill> cardBillList = cardBillMapper.selectList(params);
        for (CardBill cardBill:cardBillList) {
            if (cardBill.getType().equals(0)) {
                cardBill.setCreateDate(new Date());
                cardBill.setModifyDate(new Date());
            }
            cardBill.setMemberId(card.getMemberId());
            cardBillMapper.updateByPrimaryKeySelective(cardBill);
        }

    }


}
